Render Your Chart Using RenderChart Function
Pre-conditions
If you’ve followed the steps in the previous sections, you should have a copy of the code and be able to run it with an error on renderChart. If not, please revisit the previous lessons to get set up.
Implementing the renderChart
In this section we will be setting up renderChart function with the chartModel context.
- Clear the content inside the
renderChartfunction. - Import ChartToTSEvent from ts-chart-sdk.
- Since we will be creating some custom options in using
ChartToTSEvent.OpenContextMenu(sending post messages from chart to TS) inrenderwith labelCustom user action 1andDownload chartwe need to create some function curresponding to that. Here are the snippet for that->
function getParsedEvent(evt: any) {
return _.pick(evt.native, ["clientX", "clientY"]); // create a object with clicked position to open context menu there.
}
function downloadChartAsPNG() {
const imageLink = document.createElement("a");
const canvas = document.getElementById("chart") as any;
imageLink.download = "bar-chart.png";
imageLink.href = canvas.toDataURL("image/png", 1);
imageLink.click();
} // that will be there in onClick.
- Note:
- For more info on
CharttoTSEventrefer doc.
- For more info on
- Create a
render(ctx:CustomChartContext)function which will deal withchart.jssetup and usingdataModel.Do the following steps to create arenderfunction.
function render(ctx: CustomChartContext) {
const chartModel = ctx.getChartModel();
const dataModel = getDataModel(chartModel);
const allowLabels = _.get(chartModel.visualProps, visualPropKeyMap[2], false);
const labelColor = _.get(
chartModel.visualProps,
visualPropKeyMap[1],
availableColor[0]
);
if (!dataModel) {
return;
}
try {
const canvas = document.getElementById("chart") as any;
// clear canvas.
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
globalChartReference = new Chart(canvas as any, {
type: "bar",
data: {
labels: dataModel.getLabels(),
datasets: dataModel.getDatasets() as any,
},
options: {
animation: {
duration: 0,
},
scales: dataModel.getScales(),
plugins: {
// Change options for ALL labels of THIS CHART
datalabels: {
display: allowLabels,
color: labelColor,
labels: {
title: {
font: {
weight: "bold",
},
},
value: {
color: "black",
},
},
},
},
// responsive: true,
maintainAspectRatio: false,
interaction: {
mode: "point",
intersect: true,
},
onClick: (e: any) => {
const activeElement = e.chart.getActiveElements()[0];
const dataX = activeElement.index;
const dataY = activeElement.datasetIndex;
ctx.emitEvent(ChartToTSEvent.OpenContextMenu, {
event: getParsedEvent(e),
clickedPoint: {
tuple: dataModel.getPointDetails(dataX, dataY),
},
customActions: [
{
id: "custom-action-1",
label: "Custom user action 1",
icon: "",
onClick: (...arg) => {
console.log("custom action 1 triggered", arg);
},
},
{
id: "download-chart",
label: "Download chart",
icon: "",
onClick: () => {
downloadChartAsPNG();
},
},
],
});
},
},
plugins: [
createPlotlinePlugin(dataModel), // Add the custom plotline plugin
createPlotbandPlugin(dataModel), // Add the custom plotband plugin
],
});
} catch (e) {
console.error("renderfailed", e);
throw e;
}
}
- In
renderChartwe will be calling render function and integrating it some customCharttoTSEventthat will help in notifying ThoughtSpot different rendering stages. Copy the snippet below to implement it:
tip
For more information about the ChartToTSEvents component, refer to the following documentation resources: ChartToTSEventsPayloadMap
const renderChart = async (ctx: CustomChartContext): Promise<void> => {
try {
ctx.emitEvent(ChartToTSEvent.RenderStart);
render(ctx);
} catch (e) {
ctx.emitEvent(ChartToTSEvent.RenderError, {
hasError: true,
error: e,
});
} finally {
ctx.emitEvent(ChartToTSEvent.RenderComplete);
}
};